package com.bensonbasement.snorflux.memory;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.bensonbasement.snorflux.utils.Coords;

public class RLevel implements Serializable {
	public interface RLevelSizeChangeListener {
		public void sizeChanged(int newWidth, int newHeight);
	}
	
	private final List<RLevelSizeChangeListener> listeners = new LinkedList<RLevelSizeChangeListener>();
	
	private final Map<Coords,RSpace> spaceMap;
	private final int levelNum;
	private final RWorld world;
	
	private int knownWidth = 0;
	private int knownHeight = 0;
	
	public RLevel(RWorld world, int levelNum) {
		this.spaceMap = new HashMap<Coords,RSpace>();
		this.world = world;
		this.levelNum = levelNum;
	}
	
	
	public void addSpace(RSpace space) {
		Coords coords = space.getCoords();
		this.spaceMap.put(coords, space);
		boolean sizeChanged = false;
		if (coords.getX()+1 > this.knownWidth) {
			this.knownWidth = coords.getX()+1;
			sizeChanged = true;
		}
		if (coords.getY()+1 > this.knownHeight) {
			this.knownHeight = coords.getY()+1;
			sizeChanged = true;
		}
		if (sizeChanged) {
			this.notifyListeners();
		}
	}
	
	public RSpace getSpace(Coords coords) {
		return this.spaceMap.get(coords);
	}
	
	public RSpace getSpace(int x, int y) {
		return this.getSpace(new Coords(x,y));
	}
	
	public Collection<RSpace> getAllSpaces() {
		return this.spaceMap.values();
	}
	
	public int getLevelNum() {
		return levelNum;
	}

	public RWorld getWorld() {
		return world;
	}
	
	public void addSizeChangeListener(RLevelSizeChangeListener listener) {
		this.listeners.add(listener);
	}
	
	public void removeSizeChangeListener(RLevelSizeChangeListener listener) {
		this.listeners.remove(listener);
	}
	
	private void notifyListeners() {
		for (RLevelSizeChangeListener listener : this.listeners) {
			listener.sizeChanged(this.knownWidth, this.knownHeight);
		}
	}

	public int getKnownWidth() {
		return knownWidth;
	}


	public int getKnownHeight() {
		return knownHeight;
	}
}
